﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace BloodBot
{
    class MainMenuState : BaseState
    {
        // Global variables
        enum BState
        {
            HOVER,
            UP,
            JUST_RELEASED,
            DOWN
        }

        enum currentScreen
        {
            MainScreen, Tutorial
        }

        const int NUMBER_OF_BUTTONS = 1,
            START_BUTTON_INDEX = 0,
            BUTTON_HEIGHT = 105,
            BUTTON_WIDTH = 368;
        Color background_color;
        Color[] button_color = new Color[NUMBER_OF_BUTTONS];
        Rectangle[] button_rectangle = new Rectangle[NUMBER_OF_BUTTONS];
        BState[] button_state = new BState[NUMBER_OF_BUTTONS];
        Texture2D[] button_texture = new Texture2D[NUMBER_OF_BUTTONS];
        int renderButtonHeight,
            renderButtonWidth;
        Texture2D background, mainScreen, tutorial;
        currentScreen screen;
        MusicLoop music;

        int x, y;

        Rectangle backgroundRectangle;
        double[] button_timer = new double[NUMBER_OF_BUTTONS];
       
        double frame_time;
        Input input;

        SpriteBatch spriteBatch;

        public MainMenuState(StateManager stateManager) : base(stateManager)
        {
            music = new MusicLoop(stateManager.Game);
            music.Load();
        }

        public new void Initialize()
        {
            renderButtonWidth = (int)(((float)stateManager.Game.Window.ClientBounds.Width / 1280f) * (float)BUTTON_WIDTH);
            renderButtonHeight = (int)(((float)stateManager.Game.Window.ClientBounds.Height / 760f) * (float)BUTTON_HEIGHT);

            // starting x and y locations to stack buttons 
            // vertically in the middle of the screen
            x = stateManager.Game.Window.ClientBounds.Width / 6 - renderButtonWidth / 6;
            y = stateManager.Game.Window.ClientBounds.Height / 1 -
                NUMBER_OF_BUTTONS / 1 * renderButtonHeight -
                (NUMBER_OF_BUTTONS % 2) * renderButtonHeight / 1 - 50;
            for (int i = 0; i < NUMBER_OF_BUTTONS; i++)
            {
                button_state[i] = BState.UP;
                button_color[i] = Color.White;
                button_timer[i] = 0.0;
                button_rectangle[i] = new Rectangle(x, y, renderButtonWidth, renderButtonHeight);
                y += BUTTON_HEIGHT;
            }
            stateManager.Game.IsMouseVisible = true;
            background_color = Color.Black;

            input = new Input(stateManager.Game.GraphicsDevice.Viewport.Width,
                stateManager.Game.GraphicsDevice.Viewport.Height);

            screen = currentScreen.MainScreen;

            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = stateManager.spriteBatch;

            button_texture[START_BUTTON_INDEX] =
                stateManager.Game.Content.Load<Texture2D>(@"MenuItems/StartGameButton2");
            mainScreen = stateManager.Game.Content.Load<Texture2D>(@"MenuItems/Welcome Screen");
            tutorial = stateManager.Game.Content.Load<Texture2D>(@"MenuItems/Controls Window");

            background = mainScreen;
            //background.SetData(new Color[] { Color.Red });
            backgroundRectangle = new Rectangle(0, 0, stateManager.Game.Window.ClientBounds.Width, stateManager.Game.Window.ClientBounds.Height);
        }

        public override void Draw(GameTime gameTime)
        {
            stateManager.Game.GraphicsDevice.Clear(background_color);

            spriteBatch.Begin();

            spriteBatch.Draw(background, backgroundRectangle, Color.White);

            for (int i = 0; i < NUMBER_OF_BUTTONS; i++)
                spriteBatch.Draw(button_texture[i], button_rectangle[i], button_color[i]);
            spriteBatch.End();
        }

        public override void Update(GameTime gameTime)
        {
            if (!isStateInitialized)
            {
                this.Initialize();
            }

            music.PlayMusicLoop();

            // get elapsed frame time in seconds
            frame_time = gameTime.ElapsedGameTime.Milliseconds / 1000.0;

            input.Update();

            update_buttons();
        }


        // wrapper for hit_image_alpha taking Rectangle and Texture
        Boolean hit_image_alpha(Rectangle rect, Texture2D tex, int x, int y)
        {
            return hit_image_alpha(0, 0, tex, tex.Width * (x - rect.X) /
                rect.Width, tex.Height * (y - rect.Y) / rect.Height);
        }

        // wraps hit_image then determines if hit a transparent part of image 
        Boolean hit_image_alpha(float tx, float ty, Texture2D tex, int x, int y)
        {
            if (hit_image(tx, ty, tex, x, y))
            {
                uint[] data = new uint[tex.Width * tex.Height];
                tex.GetData<uint>(data);
                if ((x - (int)tx) + (y - (int)ty) *
                    tex.Width < tex.Width * tex.Height)
                {
                    return ((data[
                        (x - (int)tx) + (y - (int)ty) * tex.Width
                        ] &
                                0xFF000000) >> 24) > 20;
                }
            }
            return false;
        }

        // determine if x,y is within rectangle formed by texture located at tx,ty
        Boolean hit_image(float tx, float ty, Texture2D tex, int x, int y)
        {
            return (x >= tx &&
                x <= tx + tex.Width &&
                y >= ty &&
                y <= ty + tex.Height);
        }

        // determine state and color of button
        void update_buttons()
        {
            for (int i = 0; i < NUMBER_OF_BUTTONS; i++)
            {

                if (hit_image_alpha(
                    button_rectangle[i], button_texture[i], input.MouseX(), input.MouseY()))
                {
                    button_timer[i] = 0.0;
                    if (input.MouseLClick())
                    {
                        if (button_state[i] != BState.DOWN)
                        {
                            // mouse is currently down
                            if (screen == currentScreen.MainScreen)
                            {
                                background = tutorial;
                                screen = currentScreen.Tutorial;

                                x = stateManager.Game.Window.ClientBounds.Width / 10 - renderButtonWidth / 20;
                                y = stateManager.Game.Window.ClientBounds.Height / 1 -
                                    NUMBER_OF_BUTTONS / 1 * renderButtonHeight -
                                    (NUMBER_OF_BUTTONS % 1) * renderButtonHeight / 1 - 50;

                                for (int j = 0; j < NUMBER_OF_BUTTONS; j++)
                                {
                                    button_state[j] = BState.UP;
                                    button_color[j] = Color.White;
                                    button_timer[j] = 0.0;
                                    button_rectangle[j] = new Rectangle(x, y, renderButtonWidth, renderButtonHeight);
                                    y += BUTTON_HEIGHT;
                                }

                            }
                            else if (screen == currentScreen.Tutorial)
                            {
                                music.menuLoopInstance.Dispose();
                                stateManager.GoToPlayingState();
                            }
                        }

                        button_state[i] = BState.DOWN;
                        button_color[i] = Color.DarkRed;
                    }
                    else if (input.MouseLClickSwitch())
                    {
                        // mouse was just released
                        if (button_state[i] == BState.DOWN)
                        {
                            // button i was just down
                            button_state[i] = BState.JUST_RELEASED;
                        }
                    }
                    else
                    {
                        button_state[i] = BState.HOVER;
                        button_color[i] = Color.Red;
                    }
                }
                else
                {
                    button_state[i] = BState.UP;
                    if (button_timer[i] > 0)
                    {
                        button_timer[i] = button_timer[i] - frame_time;
                    }
                    else
                    {
                        button_color[i] = Color.White;
                    }
                }

                if (button_state[i] == BState.JUST_RELEASED)
                {
                    take_action_on_button(i);
                }
            }
        }


        // Logic for each button click goes here
        void take_action_on_button(int i)
        {
            //take action corresponding to which button was clicked
            switch (i)
            {
                case START_BUTTON_INDEX:
                    background_color = Color.Red;
                    break;
                default:
                    break;
            }
        }
    }
}
